package server

import (
	prom "github.com/go-kratos/kratos/contrib/metrics/prometheus/v2"
	"github.com/go-kratos/kratos/v2/middleware/logging"
	"github.com/go-kratos/kratos/v2/middleware/metadata"
	"github.com/go-kratos/kratos/v2/middleware/metrics"
	"github.com/go-kratos/kratos/v2/middleware/tracing"
	"github.com/go-kratos/kratos/v2/middleware/validate"
	"github.com/go-kratos/swagger-api/openapiv2"
	"github.com/go-redis/redis/v8"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	v1 "kratosMiddleware/api/helloworld/v1"
	"kratosMiddleware/internal/conf"
	"kratosMiddleware/internal/middleware/token"
	"kratosMiddleware/internal/service"
	"kratosMiddleware/pkg"
	"kratosMiddleware/pkg/encoder"

	"github.com/go-kratos/kratos/v2/log"
	"github.com/go-kratos/kratos/v2/middleware/recovery"
	"github.com/go-kratos/kratos/v2/transport/http"
	"github.com/gorilla/handlers"
)

var forgetURIs = []string{
	"/login",
}

// Notice 新增一个 redisCli 参数，记得进入 cmd/kratosMiddleware 执行wire
func NewHTTPServer(c *conf.Server, greeter *service.GreeterService, logger log.Logger, redisCli *redis.Client) *http.Server {
	var opts = []http.ServerOption{
		// Notice 封装一下响应的结构，加上后返回的效果如下：
		/*
			{
			  "code": 200,
			  "reason": "",
			  "message": "Hello whw"
			}
		*/
		http.ResponseEncoder(encoder.RespEncoder),

		// 中间件 注意顺序："先进后出"
		http.Middleware(
			// kratos内置的一些中间件
			recovery.Recovery(),
			metadata.Server(),
			tracing.Server(),
			// 自定义中间件
			token.LoggingMiddleware(logger, redisCli, forgetURIs...),
			// 内置
			logging.Server(logger),
			validate.Validator(),
			metrics.Server(
				metrics.WithSeconds(prom.NewHistogram(pkg.MetricSeconds)),
				metrics.WithRequests(prom.NewCounter(pkg.MetricRequests)),
			),
		),

		// Notice CORS
		http.Filter(handlers.CORS(
			handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type", "Authorization", "auth_token"}),
			handlers.AllowedMethods([]string{"GET", "POST", "PUT", "HEAD", "OPTIONS"}),
			handlers.AllowedOrigins([]string{"*"}),
		)),
	}

	if c.Http.Network != "" {
		opts = append(opts, http.Network(c.Http.Network))
	}
	if c.Http.Addr != "" {
		opts = append(opts, http.Address(c.Http.Addr))
	}
	if c.Http.Timeout != nil {
		opts = append(opts, http.Timeout(c.Http.Timeout.AsDuration()))
	}
	srv := http.NewServer(opts...)

	// Notice 单独注册路由
	srv.HandlePrefix("/q/", openapiv2.NewHandler()) // swagger
	srv.Handle("/metrics", promhttp.Handler())      // prometheus

	// 注册服务的httpServer
	v1.RegisterGreeterHTTPServer(srv, greeter)
	return srv
}
